package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	log "github.com/sirupsen/logrus"
	"github.com/yourusername/lvm-manager/internal/api"
	"github.com/yourusername/lvm-manager/internal/domain"
	"github.com/yourusername/lvm-manager/internal/events"
	"github.com/yourusername/lvm-manager/internal/host"
	"github.com/yourusername/lvm-manager/internal/libvirtconn"
	"github.com/yourusername/lvm-manager/internal/metrics"
	"github.com/yourusername/lvm-manager/internal/network"
	"github.com/yourusername/lvm-manager/internal/snapshot"
	"github.com/yourusername/lvm-manager/internal/storage"
	"github.com/yourusername/lvm-manager/internal/tasks"
	"libvirt.org/go/libvirt"
)

const (
	DefaultListenAddr = ":8080"
	DefaultLibvirtURI = "qemu:///system"
	DefaultWorkers    = 4
)

func main() {
	// 配置日志
	log.SetFormatter(&log.JSONFormatter{})
	log.SetLevel(log.InfoLevel)
	log.SetOutput(os.Stdout)

	// 从环境变量读取配置
	listenAddr := getEnv("LISTEN_ADDR", DefaultListenAddr)
	libvirtURI := getEnv("LIBVIRT_URI", DefaultLibvirtURI)
	logLevel := getEnv("LOG_LEVEL", "info")

	// 设置日志级别
	if level, err := log.ParseLevel(logLevel); err == nil {
		log.SetLevel(level)
	}

	log.Infof("Starting LVM Manager Daemon v0.2.0")
	log.Infof("Listen address: %s", listenAddr)
	log.Infof("Libvirt URI: %s", libvirtURI)

	// 创建连接管理器
	connMgr := libvirtconn.NewConnManager(libvirtURI)
	if err := connMgr.Connect(); err != nil {
		log.Fatalf("Failed to connect to libvirt: %v", err)
	}
	defer connMgr.Close()

	// 打印能力信息
	if caps := connMgr.GetCapabilities(); caps != nil {
		log.Infof("Hypervisor: %s, Libvirt version: %d",
			caps.Hypervisor, caps.LibvirtVersion)
	}

	// 创建宿主机管理器
	hostManager := host.NewHostManager()

	// 添加默认宿主机
	if err := hostManager.AddHost("default", libvirtURI); err != nil {
		log.Warnf("Failed to add default host: %v", err)
	}

	// 创建事件管理器
	var eventMgr *events.Manager
	connMgr.WithConn(func(conn *libvirt.Connect) error {
		eventMgr = events.NewManager(conn)
		return nil
	})

	// 创建服务
	domainSvc := domain.NewService(connMgr, eventMgr, log.StandardLogger())
	snapshotSvc := snapshot.NewService(connMgr)
	storageSvc := storage.NewService(connMgr)
	networkSvc := network.NewService(connMgr)

	// 创建任务队列
	taskStore := tasks.NewMemoryStore()
	taskQueue := tasks.NewQueue(DefaultWorkers, taskStore)

	// 注册任务处理器
	registerTaskHandlers(taskQueue, domainSvc, snapshotSvc, storageSvc, networkSvc)

	// 启动任务队列
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	taskQueue.Start(ctx)
	defer taskQueue.Stop()

	// 创建指标收集器
	collector := metrics.NewCollector()
	collector.SetConnectionStatus(true)

	// 启动指标更新器
	metricsUpdater := metrics.NewMetricsUpdater(collector, 30*time.Second)
	registerMetricsUpdaters(metricsUpdater, collector, connMgr, domainSvc, storageSvc, networkSvc, taskQueue)
	metricsUpdater.Start()
	defer metricsUpdater.Stop()

	// 设置 Gin
	if logLevel != "debug" {
		gin.SetMode(gin.ReleaseMode)
	}
	router := gin.New()
	router.Use(gin.Recovery())
	router.Use(loggingMiddleware())
	router.Use(corsMiddleware())
	router.Use(metricsMiddleware(collector))

	// 注册路由
	handler := api.NewHandler(domainSvc, snapshotSvc, storageSvc, networkSvc, taskQueue, hostManager)
	handler.RegisterRoutes(router)

	// Prometheus metrics
	router.GET("/metrics", gin.WrapH(promhttp.Handler()))

	// 创建 HTTP 服务器
	srv := &http.Server{
		Addr:         listenAddr,
		Handler:      router,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
		IdleTimeout:  60 * time.Second,
	}

	// 启动服务器
	go func() {
		log.Infof("HTTP server listening on %s", listenAddr)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("Failed to start HTTP server: %v", err)
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Info("Shutting down server...")

	// 优雅关闭
	shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer shutdownCancel()

	if err := srv.Shutdown(shutdownCtx); err != nil {
		log.Errorf("Server forced to shutdown: %v", err)
	}

	log.Info("Server exited")
}

// registerTaskHandlers 注册任务处理器
func registerTaskHandlers(
	taskQueue *tasks.Queue,
	domainSvc *domain.Service,
	snapshotSvc *snapshot.Service,
	storageSvc *storage.Service,
	networkSvc *network.Service,
) {
	// Domain 操作任务
	taskQueue.RegisterHandler("domain.create", func(ctx context.Context, task *tasks.Task) error {
		spec := &domain.CreateSpec{}
		payloadBytes, _ := json.Marshal(task.Payload)
		if err := json.Unmarshal(payloadBytes, spec); err != nil {
			return fmt.Errorf("failed to unmarshal domain create spec: %w", err)
		}

		_, err := domainSvc.Create(spec)
		return err
	})

	taskQueue.RegisterHandler("domain.start", func(ctx context.Context, task *tasks.Task) error {
		name, ok := task.Payload["name"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}
		return domainSvc.Start(name)
	})

	taskQueue.RegisterHandler("domain.shutdown", func(ctx context.Context, task *tasks.Task) error {
		name, ok := task.Payload["name"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}
		return domainSvc.Shutdown(name)
	})

	taskQueue.RegisterHandler("domain.destroy", func(ctx context.Context, task *tasks.Task) error {
		name, ok := task.Payload["name"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}
		return domainSvc.Destroy(name)
	})

	taskQueue.RegisterHandler("domain.undefine", func(ctx context.Context, task *tasks.Task) error {
		name, ok := task.Payload["name"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}

		force := false
		if f, ok := task.Payload["force"].(bool); ok {
			force = f
		}

		return domainSvc.Undefine(name, force)
	})

	// Snapshot 创建任务
	taskQueue.RegisterHandler("snapshot.create", func(ctx context.Context, task *tasks.Task) error {
		domainName, ok := task.Payload["domain"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}

		spec := &snapshot.CreateSpec{}
		payloadBytes, _ := json.Marshal(task.Payload["spec"])
		if err := json.Unmarshal(payloadBytes, spec); err != nil {
			return fmt.Errorf("failed to unmarshal snapshot create spec: %w", err)
		}

		_, err := snapshotSvc.Create(domainName, spec)
		return err
	})

	taskQueue.RegisterHandler("snapshot.delete", func(ctx context.Context, task *tasks.Task) error {
		domainName, ok := task.Payload["domain"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}

		snapshotName, ok := task.Payload["snapshot"].(string)
		if !ok {
			return fmt.Errorf("missing snapshot name in payload")
		}

		deleteChildren := false
		if dc, ok := task.Payload["delete_children"].(bool); ok {
			deleteChildren = dc
		}

		return snapshotSvc.Delete(domainName, snapshotName, deleteChildren)
	})

	taskQueue.RegisterHandler("snapshot.revert", func(ctx context.Context, task *tasks.Task) error {
		domainName, ok := task.Payload["domain"].(string)
		if !ok {
			return fmt.Errorf("missing domain name in payload")
		}

		snapshotName, ok := task.Payload["snapshot"].(string)
		if !ok {
			return fmt.Errorf("missing snapshot name in payload")
		}

		force := false
		if f, ok := task.Payload["force"].(bool); ok {
			force = f
		}

		return snapshotSvc.Revert(domainName, snapshotName, force)
	})

	// Storage 扩展任务
	taskQueue.RegisterHandler("storage.pool.create", func(ctx context.Context, task *tasks.Task) error {
		spec := &storage.CreatePoolSpec{}
		payloadBytes, _ := json.Marshal(task.Payload)
		if err := json.Unmarshal(payloadBytes, spec); err != nil {
			return fmt.Errorf("failed to unmarshal storage pool create spec: %w", err)
		}

		_, err := storageSvc.CreatePool(spec)
		return err
	})

	taskQueue.RegisterHandler("storage.pool.delete", func(ctx context.Context, task *tasks.Task) error {
		name, ok := task.Payload["name"].(string)
		if !ok {
			return fmt.Errorf("missing pool name in payload")
		}

		deleteVolumes := false
		if dv, ok := task.Payload["delete_volumes"].(bool); ok {
			deleteVolumes = dv
		}

		return storageSvc.DeletePool(name, deleteVolumes)
	})

	taskQueue.RegisterHandler("storage.volume.create", func(ctx context.Context, task *tasks.Task) error {
		spec := &storage.CreateVolumeSpec{}
		payloadBytes, _ := json.Marshal(task.Payload)
		if err := json.Unmarshal(payloadBytes, spec); err != nil {
			return fmt.Errorf("failed to unmarshal storage volume create spec: %w", err)
		}

		_, err := storageSvc.CreateVolume(spec)
		return err
	})

	taskQueue.RegisterHandler("storage.volume.delete", func(ctx context.Context, task *tasks.Task) error {
		poolName, ok := task.Payload["pool"].(string)
		if !ok {
			return fmt.Errorf("missing pool name in payload")
		}

		volumeName, ok := task.Payload["volume"].(string)
		if !ok {
			return fmt.Errorf("missing volume name in payload")
		}

		return storageSvc.DeleteVolume(poolName, volumeName)
	})

	// Network 创建任务
	taskQueue.RegisterHandler("network.create", func(ctx context.Context, task *tasks.Task) error {
		spec := &network.CreateSpec{}
		payloadBytes, _ := json.Marshal(task.Payload)
		if err := json.Unmarshal(payloadBytes, spec); err != nil {
			return fmt.Errorf("failed to unmarshal network create spec: %w", err)
		}

		_, err := networkSvc.Create(spec)
		return err
	})

	taskQueue.RegisterHandler("network.delete", func(ctx context.Context, task *tasks.Task) error {
		name, ok := task.Payload["name"].(string)
		if !ok {
			return fmt.Errorf("missing network name in payload")
		}

		return networkSvc.Delete(name)
	})

	// Task 删除任务
	taskQueue.RegisterHandler("task.delete", func(ctx context.Context, task *tasks.Task) error {
		taskID, ok := task.Payload["task_id"].(string)
		if !ok {
			return fmt.Errorf("missing task_id in payload")
		}

		return taskQueue.Delete(taskID)
	})
}

func registerMetricsUpdaters(
	metricsUpdater *metrics.MetricsUpdater,
	collector *metrics.Collector,
	connMgr *libvirtconn.ConnManager,
	domainSvc *domain.Service,
	storageSvc *storage.Service,
	networkSvc *network.Service,
	taskQueue *tasks.Queue,
) {
	// 注册 Domain 指标更新器
	metricsUpdater.RegisterUpdateFunc(func() {
		updateDomainMetrics(collector, domainSvc)
	})

	// 注册 Storage 指标更新器
	metricsUpdater.RegisterUpdateFunc(func() {
		updateStorageMetrics(collector, storageSvc)
	})

	// 注册 Network 指标更新器
	metricsUpdater.RegisterUpdateFunc(func() {
		updateNetworkMetrics(collector, networkSvc)
	})

	// 注册 Task 指标更新器
	metricsUpdater.RegisterUpdateFunc(func() {
		updateTaskMetrics(collector, taskQueue)
	})

	// 注册 Connection 指标更新器
	metricsUpdater.RegisterUpdateFunc(func() {
		updateConnectionMetrics(collector, connMgr)
	})
}

// updateDomainMetrics 更新 Domain 指标
func updateDomainMetrics(collector *metrics.Collector, domainSvc *domain.Service) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Failed to update domain metrics: %v", r)
		}
	}()

	// 获取所有 domains
	domains, err := domainSvc.List(true) // 包含非活跃的
	if err != nil {
		log.Errorf("Failed to list domains for metrics: %v", err)
		return
	}

	// 统计数据
	persistentCount := 0
	transientCount := 0
	stateCount := make(map[string]int)

	for _, domain := range domains {
		if domain.Persistent {
			persistentCount++
		} else {
			transientCount++
		}
		stateCount[domain.State]++
	}

	// 更新指标
	collector.UpdateDomainMetrics(persistentCount, transientCount, stateCount)
}

// updateStorageMetrics 更新 Storage 指标
func updateStorageMetrics(collector *metrics.Collector, storageSvc *storage.Service) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Failed to update storage metrics: %v", r)
		}
	}()

	// 获取所有存储池
	pools, err := storageSvc.ListPools(true) // 包含非活跃的
	if err != nil {
		log.Errorf("Failed to list storage pools for metrics: %v", err)
		return
	}

	// 统计数据
	activeCount := 0
	inactiveCount := 0

	for _, pool := range pools {
		if pool.State == "active" {
			activeCount++
		} else {
			inactiveCount++
		}

		// 更新存储池容量指标
		collector.UpdateStoragePoolCapacity(pool.Name, pool.Capacity, pool.Allocation, pool.Available)

		// 获取存储卷信息
		volumes, err := storageSvc.ListVolumes(pool.Name)
		if err != nil {
			log.Warnf("Failed to list volumes in pool %s: %v", pool.Name, err)
			continue
		}

		// 更新存储卷指标
		collector.UpdateStorageVolumeMetrics(pool.Name, len(volumes))
	}

	// 更新存储池指标
	collector.UpdateStoragePoolMetrics(activeCount, inactiveCount)
}

// updateNetworkMetrics 更新 Network 指标
func updateNetworkMetrics(collector *metrics.Collector, networkSvc *network.Service) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Failed to update network metrics: %v", r)
		}
	}()

	// 获取所有网络
	networks, err := networkSvc.List(true) // 包含非活跃的
	if err != nil {
		log.Errorf("Failed to list networks for metrics: %v", err)
		return
	}

	// 统计数据
	activeCount := 0
	inactiveCount := 0

	for _, network := range networks {
		if network.Active {
			activeCount++
		} else {
			inactiveCount++
		}
	}

	// 更新指标
	collector.UpdateNetworkMetrics(activeCount, inactiveCount)
}

// updateTaskMetrics 更新 Task 指标
func updateTaskMetrics(collector *metrics.Collector, taskQueue *tasks.Queue) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Failed to update task metrics: %v", r)
		}
	}()

	// 统计各状态的任务数量
	statusCount := make(map[string]map[string]int)

	// 获取所有状态的任务
	statuses := []tasks.Status{
		tasks.StatusPending,
		tasks.StatusRunning,
		tasks.StatusCompleted,
		tasks.StatusFailed,
		tasks.StatusRetrying,
	}

	for _, status := range statuses {
		taskList := taskQueue.List(status)
		if statusCount[string(status)] == nil {
			statusCount[string(status)] = make(map[string]int)
		}

		// 按任务类型统计
		for _, task := range taskList {
			statusCount[string(status)][task.Type]++
		}
	}

	// 更新指标
	collector.UpdateTaskMetrics(statusCount)
}

// updateConnectionMetrics 更新 Connection 指标
func updateConnectionMetrics(collector *metrics.Collector, connMgr *libvirtconn.ConnManager) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Failed to update connection metrics: %v", r)
		}
	}()

	// 检查连接状态
	connected := connMgr.IsConnected()
	collector.SetConnectionStatus(connected)
}

func metricsMiddleware(collector *metrics.Collector) gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		path := c.Request.URL.Path

		// 处理请求
		c.Next()

		// 记录指标
		end := time.Now()
		latency := end.Sub(start)
		statusCode := c.Writer.Status()

		// 记录请求指标
		collector.RecordHTTPRequest(path, latency, statusCode)
	}
}

// loggingMiddleware 日志中间件
func loggingMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		path := c.Request.URL.Path
		raw := c.Request.URL.RawQuery

		c.Next()

		latency := time.Since(start)
		statusCode := c.Writer.Status()
		clientIP := c.ClientIP()
		method := c.Request.Method

		if raw != "" {
			path = path + "?" + raw
		}

		log.WithFields(log.Fields{
			"status":     statusCode,
			"method":     method,
			"path":       path,
			"ip":         clientIP,
			"latency_ms": latency.Milliseconds(),
		}).Info("HTTP request")
	}
}

// corsMiddleware CORS 中间件
func corsMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}

		c.Next()
	}
}

// getEnv 获取环境变量，带默认值
func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}
